package jmercury;

import dblib.DB;
import dblib.PDM;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;

public class EMeterSRV extends SwingWorker {

    private ArrayList<SRVReqParser> Reqs = new ArrayList<>();
    private ArrayList<SRVReqParser> dReqs = new ArrayList<>();
    private int doneCount = 0;
    private int errCount = 0;

    private static class SRVReqParser extends Thread {

        private int cmdK;
        private int meterId;
        private String command;
        private String status = "nop";
        private int progress = 0;

        public SRVReqParser(int cmdK, int meterId, String command) {
            this.cmdK = cmdK;
            this.meterId = meterId;
            this.command = command;
            Logs.log(2, getClass().toString(), "new SRVReqParser created. cmdK = " + cmdK + ", meterId = " + meterId + ", command = " + command);
        }

        public int getCmdK() {
            return cmdK;
        }

        public int getMeterId() {
            return meterId;
        }

        public String getCommand() {
            return command;
        }

        public String getStatus() {
            return status;
        }

        public int getProgress() {
            return progress;
        }

        @Override
        public void run() {
            Logs.log(2, getClass().toString(), "SRVReqParser started. cmdK = " + cmdK + ", meterId = " + meterId + ", command = " + command);
            this.status = "run";
            while (!isInterrupted()) {
                if (command.equals("updateAvgARs")) {
                    updateAvgARs();
                    break;
                }
                if (command.equals("getMeterData")) {
                    getMeterData();
                    break;
                }
                if (command.equals("updateMonthes")) {
                    updateMonthes();
                    break;
                }
                if (command.equals("updateDays")) {
                    updateDays();
                    break;
                }
                if (command.equals("testCMD")) {
                    testCMD();
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(EMeterSRV.class.getName()).log(Level.SEVERE, null, ex);
                }
                this.status = "cmderr";
                return;
            }
        }

        private EMeter getEMeter() {
            EMeter meter = null;
            DB db = new DB();
            ResultSet rs = db.getResultSet("SELECT k, `name`, port, address, ki, ku FROM meters WHERE k = " + this.meterId + " AND hide = 0");
            try {
                while (rs.next()) {
                    int k = rs.getInt("k");
                    String name = DB.getStringFromHex(rs.getString("name"));
                    String com = DB.getStringFromHex(rs.getString("port"));
                    int addr = rs.getInt("address");
                    int ki = rs.getInt("ki");
                    int ku = rs.getInt("ku");
                    meter = new EMeter(name, ki, ku, com, addr, k);
                    meter.setDelay(500);
                }
            } catch (SQLException ex) {
                Logger.getLogger(EMeterSRV.class.getName()).log(Level.SEVERE, null, ex);
            }
            db.closeResultSet();
            return meter;
        }

        private void updateAvgARs() {
            Logs.log(2, getClass().toString(), "updateAvgARs started. meterId = " + this.meterId + ", cmdK = " + this.cmdK);

            DB db = new DB();
            EMeter meter = this.getEMeter();
            Calendar lastDTInMeter;
            Calendar lastDTInDB;
            AvgAR aar;

            Logs.log(2, getClass().toString(), "updateAvgARs - getting first aar. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            try {
                aar = meter.getAvgARLast();
                if (aar == null) {
                    Logs.log(1, getClass().toString(), "updateAvgARs - first aar == null (throwing Exception). meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                    //System.out.println("throw new Exception()");
                    throw new Exception();
                }
            } catch (Exception exc) {
                int errcount = 0;
                aar = null;
                //System.out.println(meter.getMeterName() + ": err0");
                Logs.log(1, getClass().toString(), "updateAvgARs - first aar - Exception catched. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errorcount = " + errcount);
                while (errcount < 3) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(EMeterSRV.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        Logs.log(1, getClass().toString(), "updateAvgARs - first aar - Exception catched, retrying to read aar. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errorcount = " + errcount);
                        aar = meter.getAvgARCurr();
                        if (aar == null) {
                            //System.out.println("throw new Exception() - 2");
                            throw new Exception();
                        }
                    } catch (Exception ex) {
                        Logs.log(1, getClass().toString(), "updateAvgARs - first aar - Exception catched, error reading aar. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errorcount = " + errcount);
                        errcount++;
                        //System.out.println(meter.getMeterName() + ": err 2 - " + errcount);
                        continue;
                    }
                    Logs.log(1, getClass().toString(), "updateAvgARs - first aar - Exception catched, aar rereaded (Ok)! meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errorcount = " + errcount);
                    //System.out.println(meter.getMeterName() + ": err OK");
                    break;
                }
                if (aar == null) {
                    Logs.log(1, getClass().toString(), "updateAvgARs - first aar - Exception catched, errcount = " + errcount + ", communications error! meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                    System.out.println(meter.getMeterName() + ": communications error!");
                    this.status = "err";
                    return;
                }
            }

            lastDTInMeter = aar.getArDT();
            Logs.log(2, getClass().toString(), "updateAvgARs - first aar getted, lastDTInMeter = " + DB.getDTString(lastDTInMeter) + ". meterId = " + this.meterId + ", cmdK = " + this.cmdK);

            Object firstKo = db.getScalar("SELECT `k` FROM avgars WHERE meter_id = " + meterId + " AND `hide` = false ORDER BY `arDT` DESC LIMIT 1");
            int firstK = (firstKo == null) ? 0 : (int) firstKo;

            Timestamp ts = (Timestamp) db.getScalar("SELECT `arDT` FROM avgars WHERE meter_id = " + meterId + " AND `hide` = false ORDER BY `arDT` DESC LIMIT 1");
            if (ts != null) {
                lastDTInDB = new GregorianCalendar();
                lastDTInDB.setTimeInMillis(ts.getTime());
            } else {
                lastDTInDB = (Calendar) lastDTInMeter.clone();
                lastDTInDB.add(Calendar.MONTH, -3);
            }

            Logs.log(2, getClass().toString(), "updateAvgARs - lastDTInDB getted, lastDTInDB = " + DB.getDTString(lastDTInDB) + ". meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            //System.out.println(meter.getMeterName() + ": lastDTInMeter = " + lastDTInMeter.getTime() + ", lastDTInDB = " + lastDTInDB.getTime());
            long lpr100 = lastDTInMeter.getTimeInMillis() - lastDTInDB.getTimeInMillis();

            PDM pdm = new PDM();

            Logs.log(2, getClass().toString(), "updateAvgARs - starting aar cycle. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            while (lastDTInMeter.after(lastDTInDB) && !isInterrupted()) {
                long lpr = lpr100 - (lastDTInMeter.getTimeInMillis() - lastDTInDB.getTimeInMillis());
                int perc = (int) (lpr * 100 / lpr100);
                if (perc > 100) {
                    perc = 100;
                }
                progress = perc;

                pdm.executeNonQuery("em", "INSERT INTO avgars ("
                        + "meter_id, `Aplus`, `Aminus`, `Rplus`, `Rminus`, `arPeriod`, `arDT`, hide) VALUES ("
                        + meterId + ", "
                        + aar.getAplus() + ", "
                        + aar.getAminus() + ", "
                        + aar.getRplus() + ", "
                        + aar.getRminus() + ", "
                        + aar.getArPeriod() + ", "
                        + "'" + DB.getDTString(lastDTInMeter) + "', "
                        + "true)");
                try {
                    aar = meter.getAvgARPrev();
                    if (aar == null) {
                        //System.out.println("throw new Exception() telo");
                        Logs.log(1, getClass().toString(), "updateAvgARs - aar cycle - aar == null (throwing Exception). meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                        throw new Exception();
                    }
                } catch (Exception exc) {
                    int errcount = 0;
                    aar = null;
                    //System.out.println(meter.getMeterName() + " telo: err0");
                    while (errcount < 3) {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(EMeterSRV.class.getName()).log(Level.SEVERE, null, ex);
                        }
                        try {
                            Logs.log(1, getClass().toString(), "updateAvgARs - aar cycle - Exception catched, retrying to read aar. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errorcount = " + errcount);
                            aar = meter.getAvgARCurr();
                            if (aar == null) {
                                throw new Exception();
                            }
                        } catch (Exception ex) {
                            errcount++;
                            //System.out.println(meter.getMeterName() + ": err telo - " + errcount);
                            Logs.log(1, getClass().toString(), "updateAvgARs - aar cycle - Exception catched, error reading aar. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errorcount = " + errcount);
                            continue;
                        }
                        //System.out.println(meter.getMeterName() + ": err telo OK");
                        Logs.log(1, getClass().toString(), "updateAvgARs - aar cycle - Exception catched, aar rereaded (Ok). meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errorcount = " + errcount);
                        break;
                    }
                    if (aar == null) {
                        Logs.log(1, getClass().toString(), "updateAvgARs - aar cycle - Exception catched, errcount = " + errcount + ", communications error! meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                        System.out.println(meter.getMeterName() + ": communications error!");
                        this.status = "err";
                        return;
                    }
                }
                lastDTInMeter = aar.getArDT();
            }

            pdm.executeNonQuery("em", "UPDATE avgars SET `hide` = false WHERE meter_id = " + meterId + " AND k > " + firstK);

            this.status = "done";

            Logs.log(2, getClass().toString(), "updateAvgARs - done. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
        }

        private void getMeterData() {
            EMeter meter = this.getEMeter();
            double u1 = 0, u2 = 0, u3 = 0;
            double i1 = 0, i2 = 0, i3 = 0;
            double p1 = 0, p2 = 0, p3 = 0;
            double q1 = 0, q2 = 0, q3 = 0;
            double s1 = 0, s2 = 0, s3 = 0;
            double f = 0;
            Calendar valDT = null;

            int errcount = 0;
            while (errcount < 3) {
                try {
                    u1 = meter.getU1();
                    progress = 6;
                    u2 = meter.getU2();
                    progress = 12;
                    u3 = meter.getU3();
                    progress = 18;
                    i1 = meter.getI1();
                    progress = 24;
                    i2 = meter.getI2();
                    progress = 30;
                    i3 = meter.getI3();
                    progress = 36;
                    p1 = meter.getP1();
                    progress = 42;
                    p2 = meter.getP2();
                    progress = 48;
                    p3 = meter.getP3();
                    progress = 54;
                    q1 = meter.getQ1();
                    progress = 60;
                    q2 = meter.getQ2();
                    progress = 66;
                    q3 = meter.getQ3();
                    progress = 72;
                    s1 = meter.getS1();
                    progress = 78;
                    s2 = meter.getS2();
                    progress = 84;
                    s3 = meter.getS3();
                    progress = 90;
                    f = meter.getFreq();
                    progress = 96;
                    valDT = meter.getMeterTime();
                    if (valDT == null) {
                        throw new Exception();
                    }
                    progress = 100;
                    errcount = 0;
                    break;
                } catch (Exception ex) {
                    errcount++;
                    //System.out.println(meter.getMeterName() + ": err - " + errcount);
                }
            }
            if (errcount != 0) {
                System.out.println(meter.getMeterName() + ": communications error!");
                this.status = "err";
                return;
            }

            PDM pdm = new PDM();
            pdm.executeNonQuery("em", "INSERT INTO metervals ("
                    + "meter_id, `U1`, `U2`, `U3`, `I1`, `I2`, `I3`, `P1`, `P2`, `P3`, `Q1`, `Q2`, `Q3`, `S1`, `S2`, `S3`, `F`, `valDT`, hide) "
                    + "VALUES ("
                    + meterId + ", "
                    + u1 + ", "
                    + u2 + ", "
                    + u3 + ", "
                    + i1 + ", "
                    + i2 + ", "
                    + i3 + ", "
                    + p1 + ", "
                    + p2 + ", "
                    + p3 + ", "
                    + q1 + ", "
                    + q2 + ", "
                    + q3 + ", "
                    + s1 + ", "
                    + s2 + ", "
                    + s3 + ", "
                    + f + ", "
                    + "'" + DB.getDTString(valDT) + "', "
                    + "false)");

            this.status = "done";
        }

        private void updateMonthes() {
            DB db = new DB();
            EMeter meter = this.getEMeter();
            Calendar ca = null;

            int errcount = 0;
            while (errcount < 3) {
                try {
                    ca = meter.getMeterTime();
                    if (ca == null) {
                        throw new Exception();
                    }
                    errcount = 0;
                    break;
                } catch (Exception ex) {
                    errcount++;
                    //System.out.println(meter.getMeterName() + ": err - " + errcount);
                }
            }
            if (errcount != 0) {
                System.out.println(meter.getMeterName() + ": communications error!");
                this.status = "err";
                return;
            }

            progress = 4;

            int mcounter = 0;
            int wet = 1;
            while (mcounter < 12) {
                mcounter++;

                AplusRplus aprp = null;
                AplusRplus aprpOnBeg = null;
                errcount = 0;
                while (errcount < 3) {
                    try {
                        aprp = meter.getAplusRplusMonth(ca.get(Calendar.MONTH) + 1);
                        if (aprp == null) {
                            throw new Exception();
                        }
                        aprpOnBeg = meter.getAplusRplusMonthBegining(ca.get(Calendar.MONTH) + 1);
                        if (aprpOnBeg == null) {
                            throw new Exception();
                        }
                        errcount = 0;
                        break;
                    } catch (Exception ex) {
                        errcount++;
                        //System.out.println(meter.getMeterName() + ": err - " + errcount);
                    }
                }
                if (errcount != 0) {
                    System.out.println(meter.getMeterName() + ": communications error!");
                    this.status = "err";
                    return;
                }

                int ra = db.executeNonQueryUpdate("UPDATE monthdata SET "
                        + "`Aplus` = " + aprp.getAplus() + ", "
                        + "`Rplus` = " + aprp.getRplus() + ", "
                        + "`AplusOnBeg` = " + aprpOnBeg.getAplus() + ", "
                        + "`RplusOnBeg` = " + aprpOnBeg.getRplus() + ", "
                        + "`wet` = " + wet + " "
                        + "WHERE meter_id = " + meterId + " AND "
                        + "YEAR(`monthDT`) = " + ca.get(Calendar.YEAR) + " AND MONTH(`monthDT`) = " + (ca.get(Calendar.MONTH) + 1) + " "
                        + "AND hide = 0");
                if (ra > 1) {
                    db.executeNonQuery("UPDATE monthdata SET "
                            + "`hide` = 1 "
                            + "WHERE meter_id = " + meterId + " AND "
                            + "YEAR(`monthDT`) = " + ca.get(Calendar.YEAR) + " AND MONTH(`monthDT`) = " + (ca.get(Calendar.MONTH) + 1) + " "
                            + "AND hide = 0");
                    ra = 0;
                }
                if (ra == 0) {
                    db.executeNonQuery("INSERT INTO monthdata (meter_id, `Aplus`, `Rplus`, `AplusOnBeg`, `RplusOnBeg`, `monthDT`, wet, hide) VALUES ("
                            + meterId + ", "
                            + aprp.getAplus() + ", "
                            + aprp.getRplus() + ", "
                            + aprpOnBeg.getAplus() + ", "
                            + aprpOnBeg.getRplus() + ", "
                            + "'" + ca.get(Calendar.YEAR) + "-" + (ca.get(Calendar.MONTH) + 1) + "-01', "
                            + wet + ", "
                            + "false)");
                }
                ca.add(Calendar.MONTH, -1);
                wet = 0;
                progress += 8;
            }

            this.status = "done";
        }

        private void updateDays() {
            Logs.log(2, getClass().toString(), "updateDays started. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            PDM pdm = new PDM();
            EMeter meter = this.getEMeter();
            Calendar ca_nowday = null;
            AplusRplus aprp_pd = null;
            AplusRplus aprp_nd = null;

            progress = 0;

            int errcount = 0;
            while (errcount < 3) {
                try {
                    Logs.log(2, getClass().toString(), "updateDays - getting ca_nowday. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                    ca_nowday = meter.getMeterTime();
                    if (ca_nowday == null) {
                        Logs.log(1, getClass().toString(), "updateDays - ca_nowday == null (throwing Exception). meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                        throw new Exception();
                    }
                    errcount = 0;
                    break;
                } catch (Exception ex) {
                    Logs.log(1, getClass().toString(), "updateDays - ca_nowday - Exception catched. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                    errcount++;
                }
            }
            if (errcount != 0) {
                Logs.log(1, getClass().toString(), "updateDays - ca_nowday - communications error. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                System.out.println(meter.getMeterName() + ": communications error!");
                this.status = "err";
                return;
            }
            Logs.log(2, getClass().toString(), "updateDays - ca_nowday getted. ca_nowday = " + DB.getDTString(ca_nowday) + ", meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);

            errcount = 0;
            while (errcount < 3) {
                try {
                    Logs.log(2, getClass().toString(), "updateDays - getting aprp_pd. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                    aprp_pd = meter.getAplusRplusPrevDay();
                    if (aprp_pd == null) {
                        Logs.log(1, getClass().toString(), "updateDays - aprp_pd == null (throwing Exception). meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                        throw new Exception();
                    }
                    Logs.log(2, getClass().toString(), "updateDays - getting aprp_nd. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                    aprp_nd = meter.getAplusRplusNowDay();
                    if (aprp_nd == null) {
                        Logs.log(1, getClass().toString(), "updateDays - aprp_nd == null (throwing Exception). meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                        throw new Exception();
                    }
                    errcount = 0;
                    break;
                } catch (Exception ex) {
                    Logs.log(1, getClass().toString(), "updateDays - aprp_pd, aprp_nd - Exception catched. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);
                    errcount++;
                }
            }
            if (errcount != 0) {
                Logs.log(1, getClass().toString(), "updateDays - aprp_pd, aprp_nd - communications error. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                System.out.println(meter.getMeterName() + ": communications error!");
                this.status = "err";
                return;
            }
            Logs.log(2, getClass().toString(), "updateDays - aprp_pd, aprp_nd getted. meterId = " + this.meterId + ", cmdK = " + this.cmdK + ", errcount = " + errcount);

            boolean berrok;

            // Remove doubles
            Logs.log(2, getClass().toString(), "updateDays - removing doubles. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            berrok = pdm.executeNonQuery("em", "UPDATE "
                    + "daydata, "
                    + "(SELECT k FROM daydata "
                    + "JOIN "
                    + "(SELECT COUNT(*) AS doubles, dayDT FROM daydata "
                    + "WHERE meter_id = " + meterId + " AND hide = 0 GROUP BY DATE(dayDT) HAVING doubles > 1) AS doubledays "
                    + "ON DATE(daydata.dayDT) = DATE(doubledays.dayDT) AND daydata.meter_id = " + meterId + ") AS daydatadw "
                    + "SET daydata.hide = 1 WHERE daydata.k = daydatadw.k");
            if (!berrok) {
                Logs.log(1, getClass().toString(), "updateDays - removing doubles. berrok == false! meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            }

//            // Fill last 3 monthes
//            Logs.log(2, getClass().toString(), "updateDays - filling last 3 monthes. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
//            berrok = pdm.executeNonQuery("em", "INSERT INTO daydata (meter_id, Aplus, Rplus, dayDT,wet, hide) "
//                    + "SELECT avgars.meter_id, "
//                    + "IFNULL(SUM(avgars.Aplus) / (60 / avgars.arPeriod), 0) AS Aplus, "
//                    + "IFNULL(SUM(avgars.Rplus) / (60 / avgars.arPeriod), 0) AS Rplus, "
//                    + "DATE(avgars.arDT) AS dayDT, "
//                    + "IF(COUNT(*) = 24 * (60 / avgars.arPeriod), 0, 1) AS wet, "
//                    + "0 AS hide "
//                    + "FROM avgars "
//                    + "WHERE avgars.meter_id = " + meterId + " AND avgars.hide = 0 AND avgars.arDT >= '2012-03-01' "
//                    + "AND DATE(avgars.`arDT`) NOT IN "
//                    + "(SELECT DATE(dayDT) FROM daydata WHERE meter_id = " + meterId + " AND hide = 0 AND dayDT >= '2012-03-01') "
//                    + "GROUP BY DATE(avgars.arDT) HAVING wet = 0");
//            if (!berrok) {
//                Logs.log(1, getClass().toString(), "updateDays - filling last 3 monthes. berrok == false! meterId = " + this.meterId + ", cmdK = " + this.cmdK);
//            }
//
//            // Fill wet
//            Logs.log(2, getClass().toString(), "updateDays - filling wet. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
//            berrok = pdm.executeNonQuery("em", "UPDATE daydata, "
//                    + "(SELECT "
//                    + "IFNULL(SUM(`Aplus`) / (60 / `arPeriod`), 0) AS Aplus, "
//                    + "IFNULL(SUM(`Rplus`) / (60 / `arPeriod`), 0) AS Rplus, "
//                    + "IF(COUNT(*) = 24 * (60 / `arPeriod`), 0, 1) AS wet, "
//                    + "IF(DATEDIFF(CURDATE(), avgars.`arDT`) > 90, 1, 0) as hideifdd, "
//                    + "daydatawet.k AS daydatawetk "
//                    + "FROM avgars JOIN "
//                    + "(SELECT k, `dayDT` FROM daydata "
//                    + "WHERE meter_id = " + meterId + " AND wet = 1 AND hide = 0) AS daydatawet ON DATE(avgars.`arDT`) = DATE(daydatawet.`dayDT`) "
//                    + "WHERE meter_id = " + meterId + " AND hide = 0 GROUP BY DATE(avgars.`arDT`)) as avgarscounted "
//                    + "SET daydata.`Aplus` = avgarscounted.Aplus, daydata.`Rplus` = avgarscounted.Rplus, daydata.wet = avgarscounted.wet, daydata.hide = avgarscounted.hideifdd "
//                    + "WHERE daydata.k = avgarscounted.daydatawetk");
//            if (!berrok) {
//                Logs.log(1, getClass().toString(), "updateDays - filling wet berrok == false! meterId = " + this.meterId + ", cmdK = " + this.cmdK);
//            }

            // Prev day
            Logs.log(2, getClass().toString(), "updateDays - writing prev day. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            ca_nowday.add(Calendar.DAY_OF_YEAR, -1);
            int ra = pdm.executeNonQueryUpdate("em", "UPDATE daydata SET "
                    + "`Aplus` = " + aprp_pd.getAplus() + ", "
                    + "`Rplus` = " + aprp_pd.getRplus() + ", "
                    + "`wet` = 0 "
                    + "WHERE meter_id = " + meterId + " "
                    + "AND DATE(`dayDT`) = DATE('" + DB.getDTString(ca_nowday) + "') "
                    + "AND hide = 0");
            if (ra > 1) {
                Logs.log(2, getClass().toString(), "updateDays - writing prev day, ra > 1. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                pdm.executeNonQuery("em", "UPDATE daydata SET "
                        + "`hide` = 1 "
                        + "WHERE meter_id = " + meterId + " "
                        + "AND DATE(`dayDT`) = DATE('" + DB.getDTString(ca_nowday) + "') "
                        + "AND hide = 0");
                ra = 0;
            }
            if (ra == 0) {
                Logs.log(2, getClass().toString(), "updateDays - writing prev day, ra = 0. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                pdm.executeNonQuery("em", "INSERT INTO daydata (meter_id, `Aplus`, `Rplus`, `dayDT`, wet, hide) VALUES ("
                        + meterId + ", "
                        + aprp_pd.getAplus() + ", "
                        + aprp_pd.getRplus() + ", "
                        + "'" + ca_nowday.get(Calendar.YEAR) + "-" + (ca_nowday.get(Calendar.MONTH) + 1) + "-" + ca_nowday.get(Calendar.DAY_OF_MONTH) + "', "
                        + "false, false)");
            }

            progress = 75;

            // Now day
            Logs.log(2, getClass().toString(), "updateDays - writing now day. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            ca_nowday.add(Calendar.DAY_OF_YEAR, 1);
            ra = pdm.executeNonQueryUpdate("em", "UPDATE daydata SET "
                    + "`Aplus` = " + aprp_nd.getAplus() + ", "
                    + "`Rplus` = " + aprp_nd.getRplus() + ", "
                    + "`wet` = 1 "
                    + "WHERE meter_id = " + meterId + " "
                    + "AND DATE(`dayDT`) = DATE('" + DB.getDTString(ca_nowday) + "') "
                    + "AND hide = 0");
            if (ra > 1) {
                Logs.log(2, getClass().toString(), "updateDays - writing now day, ra > 1. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                pdm.executeNonQuery("em", "UPDATE daydata SET "
                        + "`hide` = 1 "
                        + "WHERE meter_id = " + meterId + " "
                        + "AND DATE(`dayDT`) = DATE('" + DB.getDTString(ca_nowday) + "') "
                        + "AND hide = 0");
                ra = 0;
            }
            if (ra == 0) {
                Logs.log(2, getClass().toString(), "updateDays - writing now day, ra = 0. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
                pdm.executeNonQuery("em", "INSERT INTO daydata (meter_id, `Aplus`, `Rplus`, `dayDT`, wet, hide) VALUES ("
                        + meterId + ", "
                        + aprp_nd.getAplus() + ", "
                        + aprp_nd.getRplus() + ", "
                        + "'" + ca_nowday.get(Calendar.YEAR) + "-" + (ca_nowday.get(Calendar.MONTH) + 1) + "-" + ca_nowday.get(Calendar.DAY_OF_MONTH) + "', "
                        + "true, false)");
            }

            progress = 100;
            Logs.log(2, getClass().toString(), "updateDays done. meterId = " + this.meterId + ", cmdK = " + this.cmdK);
            this.status = "done";
        }

        private void testCMD() {
            while (progress < 100) {
                progress++;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(EMeterSRV.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            this.status = "done";
        }
    }

    @Override
    protected Object doInBackground() {
        PDM pdm = new PDM();

        while (!isCancelled()) {
            // Commands
            /*
             * Statuses: req run err done
             *
             * Commands:
             *
             * updateAvgARs - обновляет средние получасовые значения от последнего записанного до текущего.
             *
             * updateMonthes - обновляет данные о накопленной энергии по месяцам.
             *
             * getMeterData - берет актуальные данные и пишет в metervals.
             *
             * updateDays - обновляет данные о накопленной энергии по дням.
             *
             */
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(EMeterSRV.class.getName()).log(Level.SEVERE, null, ex);
            }
            ResultSet rs = pdm.getResultSet("em", "SELECT k, meter_id, command FROM commands WHERE status = 'req' AND hide = 0");
            if (rs == null) {
                Logs.log(1, getClass().toString(), "EMeterSRV - failed to get commands!");
            }
            try {
                while (rs.next()) {
                    SRVReqParser req = new SRVReqParser(rs.getInt("k"), rs.getInt("meter_id"), rs.getString("command"));

                    boolean re = false;
                    for (SRVReqParser r : Reqs) {
                        if (r.meterId == req.meterId) {
                            re = true;
                            break;
                        }
                    }
                    if (!re) {
                        Reqs.add(req);
                    }
                }
            } catch (SQLException ex) {
                Logger.getLogger(EMeterSRV.class.getName()).log(Level.SEVERE, null, ex);
            }
            pdm.closeResultSet();

            // Parse commands
            for (SRVReqParser req : Reqs) {
                if (req.getStatus().equals("done")) {
                    pdm.executeNonQueryUpdate("em", "UPDATE commands SET `status` = 'done' WHERE k = " + req.getCmdK());
                    doneCount++;
                    dReqs.add(req);
                }
                if (!req.getStatus().equals("run") && !req.getStatus().equals("nop") && !req.getStatus().equals("done")) {
                    pdm.executeNonQueryUpdate("em", "UPDATE commands SET `status` = '" + req.getStatus() + "' WHERE k = " + req.getCmdK());
                    System.out.println("REQ '" + req.getCommand() + "' setted to '" + req.getStatus() + "'.");
                    errCount++;
                    dReqs.add(req);
                }
                if (req.getStatus().equals("nop")) {
                    pdm.executeNonQueryUpdate("em", "UPDATE commands SET `status` = 'run' WHERE k = " + req.getCmdK());
                    req.start();
                }
            }
            for (SRVReqParser req : dReqs) {
                Reqs.remove(req);
            }
            dReqs.clear();
        }
        // Close undone REQs
        for (SRVReqParser req : Reqs) {
            pdm.executeNonQueryUpdate("em", "UPDATE commands SET `status` = 'err' WHERE k = " + req.getCmdK());
            req.interrupt();
            System.out.println("REQ '" + req.getCommand() + "' setted to 'err'.");
            errCount++;
        }
        return true;
    }

    public int getSrvReqParsersCount() {
        return this.Reqs.size();
    }

    public int getSrvReqDoneCount() {
        return doneCount;
    }

    public int getSrvReqErrCount() {
        return errCount;
    }

    int getAllProgress() {
        int ap = 0;
        if (Reqs.isEmpty()) {
            return 0;
        }
        for (SRVReqParser req : this.Reqs) {
            ap += req.getProgress();
        }
        ap /= Reqs.size();
        return ap;
    }
}
